package com.kingbull.recorder.slice;

import com.kingbull.recorder.ResourceTable;
import com.kingbull.recorder.utils.LogUtil;
import com.kingbull.recorder.utils.MyToast;
import com.kingbull.recorder.utils.RippleUtil;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.app.Environment;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.audio.AudioCapturerInfo;
import ohos.media.audio.AudioStreamInfo;
import om.recorder.*;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.IOException;
import java.util.Locale;

/**
 * WavRecorderAbilitySlice
 */
public class WavRecorderAbilitySlice extends AbilitySlice {
    private Recorder recorder;
    private Image recordButton;
    private Checkbox skipSilence;
    private Button pauseResumeButton;
    //录制状态
    private boolean recorderFlag = false;
    private Checkbox skipSilence2;
    private Text textSilence;
    private Component mCheckLayout;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_recorder);
        Text text = (Text) findComponentById(ResourceTable.Id_text_title);
        text.setText("Wav Recorder");
        setupRecorder();

        iniView();
        initClick();
    }

    private void iniView() {
        skipSilence = (Checkbox) findComponentById(ResourceTable.Id_skipSilence);
        skipSilence2 = (Checkbox) findComponentById(ResourceTable.Id_skipSilence_2);
        textSilence = (Text) findComponentById(ResourceTable.Id_text_silence);
        mCheckLayout = findComponentById(ResourceTable.Id_layout_check);
        recordButton = (Image) findComponentById(ResourceTable.Id_recordButton);
        pauseResumeButton = (Button) findComponentById(ResourceTable.Id_pauseResumeButton);
        RippleUtil.setComponent(pauseResumeButton);
        pauseResumeButton.setText(pauseResumeButton.getText().toUpperCase(Locale.ROOT));
    }

    private void initClick() {
        mCheckLayout.setClickedListener(component -> skipSilence.toggle());
        skipSilence.setCheckedStateChangedListener((absButton, isChecked) -> {
            skipSilence2.setChecked(isChecked);
            if (isChecked) {
                setupNoiseRecorder();
            } else {
                setupRecorder();
            }
        });
        recordButton.setClickedListener(component -> {
            if (recorderFlag) {
                return;
            }
            try {
                recorderFlag = true;
                recorder.startRecording();
            } catch (IOException e) {
                e.printStackTrace();
            }
            pauseResumeButton.setText(getString(ResourceTable.String_pause_recording).toUpperCase(Locale.ROOT));
            isPaused = false;
            skipSilence.setEnabled(false);
            mCheckLayout.setEnabled(false);
            skipSilence.setVisibility(Component.HIDE);
            skipSilence2.setVisibility(Component.VISIBLE);
            textSilence.setTextColor(new Color(Color.getIntColor("#bbbbbb")));
        });
        findComponentById(ResourceTable.Id_stopButton).setClickedListener(component -> stopRecorder());

        pauseResumeButton.setClickedListener(component -> pauseResumeRecorder());
    }

    private void stopRecorder() {
        if (!recorderFlag) {
            return;
        }
        try {
            recorderFlag = false;
            recorder.stopRecording();
        } catch (IOException e) {
            e.printStackTrace();
        }
        new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> animateVoice(0), 100);
        skipSilence.setEnabled(true);
        mCheckLayout.setEnabled(true);
        skipSilence.setVisibility(Component.VISIBLE);
        skipSilence2.setVisibility(Component.HIDE);
        textSilence.setTextColor(new Color(Color.getIntColor("#000000")));
    }

    private boolean isPaused = false;
    private void pauseResumeRecorder() {
        if (recorder == null) {
            MyToast.show2(getContext(), "Please start recording first!");
            return;
        }
        if (!isPaused) {
            pauseResumeButton.setText(getString(ResourceTable.String_resume_recording).toUpperCase(Locale.ROOT));
            recorder.pauseRecording();
            new EventHandler(EventRunner.getMainEventRunner()).postTask(() -> animateVoice(0), 100);
        } else {
            pauseResumeButton.setText(getString(ResourceTable.String_pause_recording).toUpperCase(Locale.ROOT));
            recorder.resumeRecording();
        }
        isPaused = !isPaused;
    }

    private void setupRecorder() {
        recorder = OmRecorder.wav(
                new PullTransport.Default(mic(), audioChunk -> animateVoice((float) (audioChunk.maxAmplitude() / 200.0))), file());
    }

    private void setupNoiseRecorder() {
        recorder = OmRecorder.wav(
                new PullTransport.Noise(mic(),
                        audioChunk -> animateVoice((float) (audioChunk.maxAmplitude() / 200.0)),
                        new WriteAction.Default(),
                        silenceTime -> {
                            MyToast.show2(getContext(), "silence of " + silenceTime + " detected");
                            LogUtil.loge("silenceTime:" + silenceTime);
                        }, 200
                ), file()
        );
    }

    private void animateVoice(final float maxPeak) {
        AnimatorProperty animatorProperty = new AnimatorProperty(recordButton);
        animatorProperty.scaleX(1 + maxPeak).scaleY(1 + maxPeak).setDuration(10).start();
    }

    private PullableSource mic() {
        return new PullableSource.Default(
                new AudioRecordConfig.Default(
                        AudioCapturerInfo.AudioInputSource.AUDIO_INPUT_SOURCE_MIC,
                        AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT,
                        AudioStreamInfo.ChannelMask.CHANNEL_IN_MONO, 44100
                )
        );
    }

    @NotNull
    private File file() {
        String path = getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() + File.separator + "kailashdabhi.wav";
        return new File(path);
    }
}
